#ifndef CENTITY_H
#define CENTITY_H

#include <iostream>
#include <string>
#include <cmath>
#include "GL/glut.h"
#include "Texture.h"

using namespace std;

#define CIRCLE 0
#define LINE 1
#define SQUARE 2
#define POLYGON 3

//fnp == function pointer
//calls the appropriate collision function for the objects shape using COLLISION
#define CALL_FNP( object, ptrToMember ) ((object)->*(ptrToMember))
#define COLLISION( object1, object2 ) ( CALL_FNP( (object1) , (object1)->Collision[(object1)->GetShape()][(object2)->GetShape()] )((object2)) )

class CGameApp;
class CEntity;

typedef bool (CEntity::*CEntityMemFn)(CEntity* test);


struct Vector2d
{
	Vector2d( float fx, float fy ) { x = fx; y = fy; }
	Vector2d()		   { x = 0; y = 0; }
	float x;
	float y;
};


class CEntity
{
public:
	CEntity();
	virtual ~CEntity();

	virtual void Render();
	virtual void Update();

	float GetDistanceTo( CEntity* target );
	void StartExplosion();
	void UpdateExplosion();
	void StartFireAnimation();
	void UpdateFireAnimation();
	void StartDamageAnimation();
	void UpdateDamageAnimation();
	virtual void TakeDamage( float damage = 1 );
	virtual void Kill();


	bool CircleCircleCollision( CEntity* test );
	bool CircleLineCollision( CEntity* test );
	bool CircleSquareCollision( CEntity* test );// { return false; }
	bool LineCircleCollision( CEntity* test );
	bool LineLineCollision( CEntity* test );
	bool LineSquareCollision( CEntity* test );// { return false; }
	bool SquareCircleCollision( CEntity* test );
	bool SquareLineCollision( CEntity* test );
	bool SquareSquareCollision( CEntity* test );

	bool (CEntity::*Collision[3][3])( CEntity* test );

	

	virtual void Load();

	void MovePosX( float movex )			{ Pos.x += movex; }
	void MovePosY( float movey )			{ Pos.y += movey; }

	void SetGame( CGameApp* game )			{ pParent=game; }// : exit(0)  }/*if(game) {pParent = game;}*/ }
	void SetPos( Vector2d position )		{ Pos = position; }
	void SetPos( float newx, float newy )	{ Pos.x = newx; Pos.y = newy; }
	void SetPosX( float newx )				{ Pos.x = newx; }
	void SetPosY( float newy )				{ Pos.y = newy; }
	void SetOldPos( float newx, float newy) { OldPos.x = newx; OldPos.y = newy; }
	void SetOldPosX( float newx )			{ OldPos.x = newx; }
	void SetOldPosY( float newy )			{ OldPos.y = newy; }
	void SetVel( Vector2d velocity )		{ Vel = velocity; }
	void SetVel( float newx, float newy )	{ Vel.x = newx; Vel.y = newy; }
	void SetSpeed( float speed )			{ m_fSpeed = speed; }
	void SetRotateSpeed( float speed )		{ m_fRotateSpeed = speed; }
	void SetTexture( int texID )			{ m_iTexture = texID; }

	void SetFireAnimationTexture( Texture* texs );
	void SetFTextureSize( int size )		{ m_iFireAnimationSize = size; }
	void SetFFrame( int frame )				{ m_iFireAnimationFrame = frame; }
	void SetFFrameDelay( float delay )		{ m_fFireAnimationFrameDelay = delay; }
	void SetFTimer( float time )			{ m_fFireAnimationTimer = time; }
	void SetFAlive( bool life )				{ m_bFireAnimationAlive = life; }
	void SetFirePos( float x , float y )	{ FirePos.x = x; FirePos.y = y; }

	void SetExplosionTexture( Texture* texs );
	void SetETextureSize( int size )		{ m_iExplosionSize = size; }
	void SetEFrame( int frame )				{ m_iExplosionFrame = frame; }
	void SetEFrameDelay( float delay )		{ m_fExplosionFrameDelay = delay; }
	void SetETimer( float time )			{ m_fExplosionTimer = time; }
	void SetDamageTexture( int texID )		{ m_iDamageTexture = texID; }
	void SetDTimer( float time )			{ m_fDamageTimer = time; }
	void SetMaxDTime( float time )			{ m_fMaxDamageTime = time; }
	void SetDAlive( bool life )				{ m_bDamageAlive = life; }

	void SetAlive( bool life )				{ m_bAlive = life; }
	void SetEAlive( bool life )				{ m_bExplosionAlive = life; }
	void SetHealth( float health )			{ m_fHealth = health; }
	void SetDamage( float damage )			{ m_fDamage = damage; }
	void SetFaceAngle( float angle );		
	void SetFaceAngle( float x, float y );	//faces the vector past in
	//void PointTo( float x, float y );		
	void RotateFaceAngleBy( float angle );
	void SetSize( float size )				{ m_fSize = size; m_fRadius = size/2.0f; SetQuad(); }
	void SetRadius( float r )				{ m_fRadius = r; m_fSize = r*2; SetQuad(); }
	void SetCollisionSize( float size )		{ m_fCollisionSize = size; m_fCollisionRadius = size/2.0f; }
	void SetCollisionRadius( float r )		{ m_fCollisionRadius = r; m_fCollisionSize = r*2; }
	void SetType( string type )				{ m_sType = type; }
	void SetShape( int shape )				{ m_iShape = shape; }
	void SetDistanceToPlayer( float distance ) { m_fDistanceToPlayer = distance; }
	void SetLifeSpan( float time )			{ m_fLifeSpan = time; }
	void SetLaserLength( float length )		{ m_fLaserLength = length; }
	void SetLaserFiring( bool isFiring )	{ m_bLaserFiring = isFiring; }
	virtual void SetQuad();
	void SetLineEnd( float length );




	CGameApp* GetGame()			{ return pParent; }
	float	 GetPosX()			{ return Pos.x; }
	float	 GetPosY()			{ return Pos.y; }
	float	 GetOldPosX()		{ return OldPos.x; }
	float	 GetOldPosY()		{ return OldPos.y; }
	float	 GetVelX()			{ return Vel.x; }
	float	 GetVelY()			{ return Vel.y; }
	Vector2d GetVel()			{ return Vel; }
	float	 GetSpeed()			{ return m_fSpeed; }
	float	 GetRotateSpeed()	{ return m_fRotateSpeed; }
	int	     GetTexture()		{ return m_iTexture; }

	int		 GetFTextureSize()	{ return m_iFireAnimationSize; }
	int		 GetFTexture(int frame)		{ return m_pFireAnimationTexture[frame]; }
	int		 GetFFrame()		{ return m_iFireAnimationFrame; }
	float	 GetFFrameDelay()	{ return m_fFireAnimationFrameDelay; }
	float	 GetFTimer()		{ return m_fFireAnimationTimer; }
	bool	 GetFAlive()		{ return m_bFireAnimationAlive; }
	float	 GetFirePosX()		{ return FirePos.x; }
	float	 GetFirePosY()		{ return FirePos.y; }

	int		 GetETextureSize()	{ return m_iExplosionSize; }
	int		 GetETexture(int frame)		{ return m_pExplosionTexture[frame]; }
	int		 GetEFrame()		{ return m_iExplosionFrame; }
	float	 GetEFrameDelay()	{ return m_fExplosionFrameDelay; }
	float	 GetETimer()		{ return m_fExplosionTimer; }

	int		 GetDTexture()		{ return m_iDamageTexture; }
	float	 GetDTimer()		{ return m_fDamageTimer; }
	float	 GetMaxDamageTime()	{ return m_fMaxDamageTime; }
	bool	 GetDAlive()		{ return m_bDamageAlive; }

	bool	 GetAlive()			{ return m_bAlive; }
	bool	 GetEAlive()		{ return m_bExplosionAlive; }
	float	 GetHealth()		{ return m_fHealth; }
	float	 GetDamage()		{ return m_fDamage; }
	float	 GetFaceAngle()		{ return m_fFaceAngle; }
	float	 GetSize()			{ return m_fSize; }
	float	 GetRadius()		{ return m_fRadius; }
	float	 GetCollisionSize()	{ return m_fCollisionSize; }
	float	 GetCollisionRadius(){return m_fCollisionRadius; }
	string	 GetType()			{ return m_sType; }
	int		 GetShape()			{ return m_iShape; }
	float	 GetDistanceToPlayer() { return m_fDistanceToPlayer; }
	float	 GetLifeSpan()		{ return m_fLifeSpan; }
	float	 GetLaserLength()	{ return m_fLaserLength; }
	bool	 GetLaserFiring()	{ return m_bLaserFiring; }



	Vector2d Pos;
	Vector2d OldPos;
	Vector2d Vel;

	float   m_fSpeed;				//the speed of the entity
	float	m_fRotateSpeed;			//the rotation speed of the entity
	int		m_iTexture;				//the texID needed to draw the texture

	//this animation stuff could use its own class. the object itself still needs an animation texture, plus move/ware and tare
	int*	m_pFireAnimationTexture;//the texID's of the fire animation texture
	int		m_iFireAnimationSize;	//size of the array of fire animation textures
	int		m_iFireAnimationFrame;	//current frame of animation for the bullet firing
	float	m_fFireAnimationFrameDelay;//time between animation frames
	float	m_fFireAnimationTimer;  //time passed since the bullet was fired
	bool	m_bFireAnimationAlive;	//whether the animation is alive
	Vector2d FirePos;				//the position of the fire animation

	int*	m_pExplosionTexture;	//the texID's of the explosion texture
	int		m_iExplosionSize;		//size of the array of textures
	int		m_iExplosionFrame;		//current frame the animation is on
	float	m_fExplosionFrameDelay; //time between animation frames
	float	m_fExplosionTimer;		//time passed since explosion started

	int		m_iDamageTexture;
	float	m_fDamageTimer;
	float	m_fMaxDamageTime;
	bool	m_bDamageAlive;

	bool	m_bAlive;				//whether the entity is alive
	bool	m_bExplosionAlive;		//whether the explosion is alive
	float	m_fHealth;				//amount of health remaining
	float	m_fDamage;				//amount of damage entity does when it collides with something
	float	m_fFaceAngle;			//the angle the entity is facing
	float	m_fSize;				//size in view space
	float	m_fRadius;				//length from center of entity to the edge
	float	m_fCollisionSize;		//diameter of bounding circle
	float	m_fCollisionRadius;		//radius of bounding circle
	float	m_fDistanceToPlayer;	//distance of this entity to the player object, created for sorting purposes
	float	m_fLifeSpan;			//for bullets, time until the bullet blows itself up or just dies and disappears
	string  m_sType;				//type of entity. player, enemy, homingweapon, etc.
	int		m_iShape;				//shape of the entity. line, circle, square, or polygon defined at top
	float	m_fLaserLength;			//distance from the ship to the end of the laser
	bool	m_bLaserFiring;			//laser firing is based on holding the trigger
	bool	Breakable;

	float	topleftx, toplefty;
	float	bottomleftx, bottomlefty;
	float	toprightx, toprighty;
	float	bottomrightx, bottomrighty;




	CGameApp* pParent;			//pointer to the game controlling this object

	//object of a class that has a function pointer and a timer
	//array of these
	//better yet, an object of a class that can have an array of function pointers



private:

};

#endif


//array of texture id's used to access the textures
//array size
//current frame
//time since start
//time between frames






